/****************************************************************************
 *
 *  LinuxChatty
 *  Copyright (C) 2010, David Hsu.
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 ***************************************************************************/
#include "MainFrame.h"
#include "ui/AboutScreen.h"
#include "ui/MainMenuScreen.h"
#include "ui/ThreadScreen.h"
#include "ui/DialogScreen.h"
#include "ui/CommentsScreen.h"
#include "ui/PostScreen.h"
#include "ui/SettingsScreen.h"
#include "ui/UIManager.h"
#include "ui/WindowInfo.h"
#include "services/UIService.h"
#include "services/ResourceTable.h"
#include "services/ThreadService.h"
#include <string.h>
#include <stdlib.h>
#include <ncurses.h>

using namespace std;

// Global UI service class that will only be called in the main file to
// initialize and shutdown the ncurses service. This allows keyboard interrupts
// to disable ncurses correctly before quitting.
UIService uiService;

// TODO: Add keyboard signal catching

int main( int argc, const char* argv[] )
{
	int threadId = -1;
	const char * debugFile = NULL;
	
	// Run time arguements for debugging
	for (int i = 0; i < argc; i++)
	{
		if (strncmp(argv[i], "-thread", 7) == 0)
		{
			// Program will go to the specified story thread instead of loading
			// the latest chatty root.
			// Next argument will be the story id
			if (i + 1 < argc)
			{
				threadId = atoi(argv[i+1]);
				// Advance an extra argument past the number
				i++;
			}
		}
		else if (strncmp(argv[i], "-file", 5) == 0)
		{
			// Program will function in offline mode and only read the
			// information from the specified file.
			// Next argument will be the file to load
			if (i + 1 < argc)
			{
				debugFile = argv[i+1];
				// Advance the extra argument past the filename
				i++;
			}
		}
	}

	// Initialize ncurses
	uiService.Initialize();
	
	// Load the resource file
	ResourceTable * resource = new ResourceTable();
	resource->LoadFile( "Resource.xml" );
	
	ThreadService * threadService = new ThreadService();
	threadService->SetAPIServer( resource->GetSelectedServer() );
	
	// Note that the UIManager has to be created after ncurses is initialized
	// since it starts creating ncurses components dependent on the return
	// terminal size, and if ncurses hasn't been initialized, then the termainal
	// size will be an invalid value.
	UIManager * manager = new UIManager(resource->GetTitle(), 
	    resource->GetVersion());
	
	// Get the current terminal resolution
	WindowInfo res = manager->GetTerminalSize();
	
	// Centering position for the main menu
	int startx = (res.width - 70) / 2;
	
	// TODO: Get rid of these hard coded numbers!
	MainMenuScreen * menuScreen = new MainMenuScreen(manager, resource,
	    WindowInfo(70, 15, 1, startx));
	ThreadScreen * threadScreen = new ThreadScreen(manager, threadService,
	    WindowInfo(res.width, res.height - 4, 1, 0), debugFile);
	CommentsScreen * commentsScreen = new CommentsScreen(manager, threadService,
	    WindowInfo(res.width, res.height - 4, 1, 0), debugFile);
	PostScreen * postScreen = new PostScreen(manager, threadService,
	    WindowInfo(res.width, res.height - 4, 1, 0));
	AboutScreen * aboutScreen = new AboutScreen(manager,
	    WindowInfo(res.width, res.height, 1, 0));
	SettingsScreen * settingsScreen = new SettingsScreen(manager, threadService,
	    resource, WindowInfo(res.width, res.height, 4, 10));
	
	// Add the screens to the UIManager
	manager->AddUI( "mainmenu", menuScreen );
	manager->AddUI( "thread", threadScreen );
	manager->AddUI( "comments", commentsScreen );
	manager->AddUI( "post", postScreen );
	manager->AddUI( "about", aboutScreen );
	manager->AddUI( "settings", settingsScreen );
	
	// DEBUGGING!
	if (threadId > 0)
		threadService->SetThreadId( threadId );
	
    // Create the main class that will handle running the program
	MainFrame mf(manager);
	mf.Run( (threadId > 0) );
	
	// Clean up the classes
	delete resource;
	delete manager;
	delete threadService;
	
	// Shutdown ncurses before exiting
	uiService.Shutdown();
	return 0;
}
